home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / util / cli / move37.lha / Move37 / move.c next >
Encoding:
C/C++ Source or Header  |  1999-10-30  |  14.0 KB  |  649 lines

  1. ;/*
  2. gcc -m68020-60 -noixemul -nostdlib -nostartfiles -msmall-code -O2 -fstrength-reduce -fomit-frame-pointer -mregparm=3 -s move.c -o c:move
  3. shortrel c:move
  4. protect c:move p add
  5. quit
  6. */
  7.  
  8. /* 
  9. **
  10. **    Move.c - (C) 1993-99 by Stephan Rupprecht
  11. **    a move command for AmigaDOS
  12. **
  13. */
  14.  
  15. #include <dos/dos.h>
  16. #include <dos/dosasl.h>
  17. #include <dos/dosextens.h>
  18. #include <exec/execbase.h>
  19.  
  20. #include <proto/dos.h>
  21. #include <proto/exec.h>
  22.  
  23. #define FULLPATHSIZE    256
  24. #define REG(reg,arg)    arg __asm(#reg)
  25.  
  26. /****************************************************************************/
  27.  
  28. struct args { 
  29.     STRPTR    *src, dst; 
  30.     LONG      as; 
  31.     LONG      noreq; 
  32.     LONG      force; 
  33.     LONG      skip; 
  34.     LONG     *buffer; 
  35.     LONG      quiet;
  36. }; 
  37.  
  38. /****************************************************************************/
  39.  
  40. LONG start( void );
  41. LONG CopyFile( struct FileInfoBlock *fib, const STRPTR to, ULONG bufsize, const struct args *args, STRPTR *move_text, REG( a6, const struct Library *DOSBase ) );
  42. LONG Delete( struct FileInfoBlock *fib, REG( a6, const struct Library *DOSBase ) );
  43. LONG CheckLoop( const STRPTR name, BPTR parent, REG( a6, const struct Library *DOSBase ) );
  44. void StrnCpy( STRPTR a, STRPTR b, REG( d1, WORD c ) );
  45.  
  46. /****************************************************************************/
  47.  
  48. LONG dummy( void )
  49. {
  50.     return start();
  51. }
  52.  
  53. /****************************************************************************/
  54.  
  55. LONG start( void )
  56.     const STRPTR     VerStr = "$VER: move 37.6 (30.10.99) © 1997-99 by Stephan Rupprecht";
  57.     struct Library    *SysBase = (*(struct Library **)4L);
  58.     struct Library    *DOSBase;
  59.     LONG              error = 0L;
  60.  
  61.     if( DOSBase = OpenLibrary( "dos.library", 37L ) )
  62.     {        
  63.         struct args args = {};
  64.         struct RDArgs *rdargs;
  65.         
  66.         if( rdargs = ReadArgs( "FROM/A/M,TO/A,AS/S,NOREQ/S,FORCE/S,SKIP/S,BUF=BUFFER/N/K,QUIET/S", (LONG *)&args, NULL ) )
  67.         {        
  68.             struct AnchorPath    *ap;
  69.             struct Process        *pr;
  70.             APTR                 win;
  71.             TEXT                 to[ FULLPATHSIZE ];
  72.             
  73.             if( args.noreq )
  74.             {
  75.                 pr = (struct Process *) FindTask( NULL );
  76.                 win = pr->pr_WindowPtr;
  77.                 pr->pr_WindowPtr = (APTR) ~0L;
  78.             }
  79.             
  80.             for( ;; )
  81.             {    
  82.                 struct InfoData    *id;
  83.                 ULONG             bufsize;
  84.             
  85.                 if( args.force && ( args.as || args.skip ) )
  86.                 {
  87.                     Printf( "FORCE can't be used in conjunction with AS or SKIP!\n" );
  88.                     break;
  89.                 }
  90.                 
  91.                 if( ! GetCurrentDirName( to, sizeof( to ) ) ||
  92.                     ! AddPart( to, args.dst, sizeof( to ) ) )
  93.                 {
  94.                     error = IoErr();
  95.                     break;                
  96.                 }
  97.  
  98.                 if( id = AllocMem( sizeof( *id ), MEMF_PUBLIC ) )
  99.                 {
  100.                     ULONG    tmp, bpp = 512L;
  101.                     TEXT    buf[ FULLPATHSIZE ];
  102.                     
  103.                     tmp = (args.as) ? ( (ULONG) PathPart( to ) - (ULONG) to ) : sizeof( buf );
  104.                     StrnCpy( buf, to, tmp );
  105.                     
  106.                     if( ! ( tmp = Lock( buf, SHARED_LOCK ) ) )
  107.                     {                    
  108.                         if( ! ( tmp = CreateDir( buf ) ) )
  109.                         {
  110.                             error = IoErr();
  111.                             break;
  112.                         }
  113.                         else if( ! args.quiet )
  114.                         {                                
  115.                             Printf( "Directory %s created.\n", (ULONG) buf );                            
  116.                         }
  117.                     }                        
  118.                     
  119.                     if( Info( tmp, id ) )
  120.                     {
  121.                         bpp = id->id_BytesPerBlock;
  122.                     }
  123.                     
  124.                     bufsize  = ( bpp * ( ( args.buffer ) ? *args.buffer : 200L ) ) / 2L;
  125.                     
  126.                     UnLock( tmp );
  127.                     
  128.                     FreeMem( id, sizeof( *id ) );                    
  129.                 }
  130.                 else
  131.                 {
  132.                     error = ERROR_NO_FREE_STORE;
  133.                     break;
  134.                 }
  135.                 
  136.                 if( ap = AllocMem( sizeof( *ap ) + FULLPATHSIZE, MEMF_CLEAR|MEMF_PUBLIC ) )
  137.                 {                
  138.                     ap->ap_BreakBits    = SIGBREAKF_CTRL_C;
  139.                     ap->ap_Strlen        = FULLPATHSIZE;
  140.                     ap->ap_Flags        = APF_FollowHLinks;
  141.                     
  142.                     while( *args.src )
  143.                     {
  144.                         LONG    depth = 0L;
  145.                         
  146.                         error = MatchFirst( *args.src, ap );
  147.                         
  148.                         while( ! error )
  149.                         {
  150.                             STRPTR    from = ap->ap_Info.fib_FileName,
  151.                                     move_text = "moved.\n";
  152.                             BPTR    lock = ap->ap_Current->an_Lock, cd;
  153.                             LONG    type = ap->ap_Info.fib_DirEntryType;
  154.                             BOOL    releaselock = FALSE;
  155.  
  156.                             if( *from == '\0' )
  157.                             {                                
  158.                                 StrnCpy( from, FilePart( ap->ap_Buf ), 108L );
  159.                             
  160.                                 if( ! ( lock = ParentDir( lock ) ) )
  161.                                 {
  162.                                     if( ! ( error = IoErr() ) )
  163.                                     {                                        
  164.                                         error = ERROR_OBJECT_WRONG_TYPE;
  165.                                     }
  166.                                 }
  167.                                     
  168.                                 releaselock = TRUE;
  169.                             }
  170.                     
  171.                             cd = CurrentDir( lock );                            
  172.                             
  173.                             if( ap->ap_Flags & APF_DIDDIR )
  174.                             {
  175.                                 ap->ap_Flags &= ~APF_DIDDIR;
  176.                                                                             
  177.                                 if( ! ( ! --depth && args.as ) )
  178.                                 {
  179.                                     *PathPart( to ) = '\0';
  180.                                 }
  181.                                 
  182.                                 error = Delete( &ap->ap_Info, DOSBase );
  183.                             }
  184.                             else
  185.                             {
  186.                                 if( ! ( args.as && ! depth ) )
  187.                                 {
  188.                                     if( ! AddPart( to, from, sizeof( to ) ) )
  189.                                     {
  190.                                         error = ERROR_BUFFER_OVERFLOW;
  191.                                     }
  192.                                 }
  193.                                 
  194.                                 #ifdef DEBUG
  195.                                 {
  196.                                     TEXT    buf[ 256 ];
  197.                                     
  198.                                     NameFromLock( lock, buf, sizeof( buf ) );
  199.                                     AddPart( buf, from, sizeof( buf ) );
  200.                                     
  201.                                     Printf(    "ap->ap_Buf: %s\n"
  202.                                             "AddPart(ed): %s -> %s (%ld)\n",
  203.                                             ap->ap_Buf, buf, to, type );
  204.                                             
  205.                                     args.quiet = TRUE;
  206.                                 }
  207.                                 #endif
  208.                                 
  209.                                 if( ! error )
  210.                                 {
  211.                                     BOOL    dodir = ( type >= 0L );
  212.                                                                         
  213.                                     if( type == ST_SOFTLINK )
  214.                                     {
  215.                                         BPTR    fh;
  216.                                         
  217.                                         if( fh = Open( from, MODE_OLDFILE ) )
  218.                                         {
  219.                                             Close( fh );
  220.                                             dodir = FALSE;
  221.                                         }
  222.                                         else if( ( error = IoErr() ) == ERROR_OBJECT_WRONG_TYPE ) 
  223.                                         {
  224.                                             error = 0L;
  225.                                         }
  226.                                     }                                        
  227.                                                     
  228.                                     if( ! args.quiet )
  229.                                     {
  230.                                         LONG    i;
  231.                                         
  232.                                         for( i = depth+1; i; i-- )
  233.                                         {
  234.                                             Printf( "     " );
  235.                                         }
  236.                                         
  237.                                         Printf( dodir ? "   %s (Dir)" : "   %s..", (ULONG) from );
  238.                                         Flush( Output() );
  239.                                     }
  240.                                     
  241.                                     if( ! error )
  242.                                     {                                        
  243.                                         if( ! Rename( from, to ) && ( ( error = IoErr() ) == ERROR_RENAME_ACROSS_DEVICES ) )
  244.                                         {
  245.                                             error = 0L;
  246.                                         
  247.                                             for( ;; )
  248.                                             {                                                                                            
  249.                                                 if( dodir )
  250.                                                 {                            
  251.                                                     BPTR    fl;
  252.                                                     
  253.                                                     move_text = "\n";
  254.                                                     
  255.                                                     depth++;
  256.                                                     
  257.                                                     ap->ap_Flags |= APF_DODIR;
  258.                                                     
  259.                                                     if( type == ST_SOFTLINK || type == ST_LINKDIR )
  260.                                                     {                                                
  261.                                                         if( error = CheckLoop( from, lock, DOSBase ) )
  262.                                                         {
  263.                                                             break;
  264.                                                         }
  265.                                                     }
  266.                                                                                                                         
  267.                                                     if( fl = CreateDir( to ) )
  268.                                                     {
  269.                                                         if( ! args.quiet ) 
  270.                                                         {
  271.                                                             Printf( "   [created]" );
  272.                                                         }
  273.                                                         
  274.                                                         UnLock( fl );
  275.                                                     }
  276.                                                     else if( ( error = IoErr() ) == ERROR_OBJECT_EXISTS )
  277.                                                     {
  278.                                                         error = 0L;
  279.                                                     }                                        
  280.                                                 }
  281.                                                 else
  282.                                                 {
  283.                                                     if( ! ( error = CopyFile( &ap->ap_Info, to, bufsize, &args, &move_text, DOSBase ) ) )
  284.                                                     {                                                
  285.                                                         error = Delete( &ap->ap_Info, DOSBase );                                                
  286.                                                     }
  287.                                                                                                                                                 
  288.                                                     if( ! ( args.as && ! depth ) )
  289.                                                     {
  290.                                                         *PathPart( to ) = '\0';
  291.                                                     }                                        
  292.                                                 }
  293.                                                             
  294.                                                 break;
  295.                                             }
  296.                                         }
  297.                                         else 
  298.                                         {                                    
  299.                                             if( error == ERROR_OBJECT_EXISTS )
  300.                                             {
  301.                                                 if( args.skip )
  302.                                                 {
  303.                                                     error = 0L;
  304.                                                     move_text = "skipped.\n";
  305.                                                 }
  306.                                                 else if( args.force )
  307.                                                 {    
  308.                                                     SetProtection( to, ~(FIBF_DELETE|FIBF_OTR_DELETE) );
  309.                                             
  310.                                                     if( DeleteFile( to ) && Rename( from, to ) )
  311.                                                     {
  312.                                                         error = 0L;
  313.                                                     }
  314.                                                 }                                                
  315.                                             }
  316.                                             
  317.                                             if( ! ( args.as && ! depth ) )
  318.                                             {
  319.                                                 *PathPart( to ) = '\0';
  320.                                             }                                
  321.                                         }
  322.                                     }
  323.                                 
  324.                                     if( ! args.quiet )
  325.                                     {
  326.                                         Printf( error ? "failed.\n" : move_text );
  327.                                     }
  328.                                 }
  329.         
  330.                                 if( error )
  331.                                 {                            
  332.                                     Printf( "Can't move %s\n", (ULONG) ap->ap_Buf );
  333.                                 }                                            
  334.                             }
  335.         
  336.                             CurrentDir( cd );
  337.                             
  338.                             if( releaselock )
  339.                             {
  340.                                 UnLock( lock );
  341.                                 *from = '\0';
  342.                             }
  343.                             
  344.                             if( ! error )
  345.                             {
  346.                                 error = MatchNext( ap );
  347.                             }
  348.                         }
  349.                         
  350.                         MatchEnd( ap );
  351.                         
  352.                         if( error == ERROR_NO_MORE_ENTRIES )
  353.                         {
  354.                             error = 0L;
  355.                         }
  356.                         
  357.                         if( error ) 
  358.                         {
  359.                             break;
  360.                         }
  361.         
  362.                         args.src++;
  363.                     }
  364.                     
  365.                     FreeMem( ap, sizeof( *ap ) + FULLPATHSIZE );
  366.                 }
  367.                 else
  368.                 {
  369.                     error = ERROR_NO_FREE_STORE;
  370.                 }                
  371.                 
  372.                 break;
  373.             }
  374.                         
  375.             if( args.noreq )
  376.             {
  377.                 pr->pr_WindowPtr = win;
  378.             }
  379.         
  380.             FreeArgs( rdargs );
  381.         }
  382.         else
  383.         {
  384.             error = IoErr();
  385.         }
  386.         
  387.         PrintFault( error, "Move" );
  388.         
  389.         CloseLibrary( DOSBase );
  390.     }
  391.     
  392.     return( error ? RETURN_ERROR : RETURN_OK );
  393. }
  394.  
  395. /****************************************************************************/
  396.  
  397. LONG CopyFile( struct FileInfoBlock *fib, const STRPTR to, ULONG bufsize, const struct args *args, STRPTR *move_text, REG( a6, const struct Library *DOSBase ) )
  398. {    
  399.     BPTR    fhin, fhout;
  400.     LONG    err = 0L;
  401.  
  402.     if( fhin = Lock( to, SHARED_LOCK ) )
  403.     {                
  404.         UnLock( fhin );
  405.     
  406.         if( args->skip )
  407.         {
  408.             *move_text = "skipped.\n";
  409.             return 0L;
  410.         }
  411.         else if( args->force )
  412.         {                
  413.             SetProtection( to, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE) );
  414.         }
  415.         else
  416.         {        
  417.             return ERROR_OBJECT_EXISTS;
  418.         }            
  419.     }
  420.  
  421.     if( fhout = Open( fib->fib_FileName, MODE_OLDFILE ) )
  422.     {                                    
  423.         if( fhin = Open( to, MODE_NEWFILE ) )
  424.         {
  425.             if( fib->fib_Size )
  426.             {                    
  427.                 struct Library    *SysBase = (*(struct Library **)4L);
  428.                 UBYTE            *buf[ 2 ], *buffer;
  429.                 ULONG             allocsize;
  430.                 
  431.                 err = ERROR_NO_FREE_STORE;
  432.                 
  433.                 if( bufsize == 0 || fib->fib_Size < bufsize )
  434.                 {
  435.                     bufsize   = fib->fib_Size;
  436.                     allocsize = bufsize;
  437.                 }
  438.                 else
  439.                 {
  440.                     allocsize = ( bufsize * 2 );
  441.                 }
  442.  
  443.                 while( ! ( buffer = AllocMem( allocsize + 15L, MEMF_PUBLIC ) ) )
  444.                 {
  445.                     bufsize /= 2;
  446.                     
  447.                     if( ( allocsize = bufsize * 2 ) < 8192L )
  448.                     {
  449.                         break;
  450.                     }
  451.                 }
  452.  
  453.                 if( buffer )
  454.                 {
  455.                     struct DosPacket    *rdp, *wdp;
  456.     
  457.                     buf[ 0 ] = (UBYTE *) (((ULONG)buffer + 15L)&0xfffffff0);
  458.                     buf[ 1 ] = buf[ 0 ] + bufsize;
  459.                     
  460.                     if( rdp = AllocDosObject( DOS_STDPKT, NULL ) )
  461.                     {
  462.                         if( wdp = AllocDosObject( DOS_STDPKT, NULL ) )
  463.                         {
  464.                             struct MsgPort    *rmp = (struct MsgPort *) ((struct FileHandle *)BADDR( fhout ))->fh_Type,
  465.                                             *wmp = (struct MsgPort *) ((struct FileHandle *)BADDR( fhin ))->fh_Type,
  466.                                             *replyport = &((struct Process *)FindTask( NULL ))->pr_MsgPort;
  467.                             LONG             index = 0, rres1;
  468.                             BOOL             first = TRUE, samedev = FALSE;                                
  469.                             /*
  470.                             ** try to determine if source and dest are on the
  471.                             ** same physical device
  472.                             */
  473.                             {
  474.                                 BPTR    l1, l2;
  475.                                 
  476.                                 if( l1 = DupLockFromFH( fhout ) )
  477.                                 {                                                                    
  478.                                     if( l2 = ParentOfFH( fhin ) )
  479.                                     {
  480.                                         samedev = SameDevice( l1, l2 );
  481.                                         UnLock( l2 );
  482.                                     }
  483.                                     
  484.                                     UnLock( l1 );                                        
  485.                                 }
  486.                             }
  487.                             
  488.                             rdp->dp_Type = ACTION_READ;
  489.                             rdp->dp_Arg1 = ((struct FileHandle *)BADDR( fhout ))->fh_Arg1;
  490.                             rdp->dp_Arg3 = samedev ? bufsize*2 : bufsize;
  491.                             
  492.                             wdp->dp_Type = ACTION_WRITE;
  493.                             wdp->dp_Arg1 = ((struct FileHandle *)BADDR( fhin ))->fh_Arg1;
  494.                             
  495.                             for( ;; )
  496.                             {                                        
  497.                                 rdp->dp_Arg2 = (LONG) buf[ index ];
  498.                                 SendPkt( rdp, rmp, replyport );
  499.                                 
  500.                                 if( ! first )
  501.                                 {
  502.                                     WaitPkt();
  503.                                 }
  504.                                 
  505.                                 WaitPkt();
  506.                                 
  507.                                 if( (rres1 = rdp->dp_Res1) <= 0 )
  508.                                 {
  509.                                     err = rdp->dp_Res2;
  510.                                     break;
  511.                                 }
  512.                                 
  513.                                 if( ! first && wdp->dp_Res1 != wdp->dp_Arg3 )
  514.                                 {
  515.                                     err = wdp->dp_Res2;
  516.                                     break;
  517.                                 }
  518.                                 
  519.                                 if( CheckSignal( SIGBREAKF_CTRL_C ) )
  520.                                 {
  521.                                     err = ERROR_BREAK;
  522.                                     break;
  523.                                 }
  524.                                 
  525.                                 wdp->dp_Arg2 = (LONG) buf[ index ];
  526.                                 wdp->dp_Arg3 = rres1;
  527.                                 SendPkt( wdp, wmp, replyport );
  528.                                 
  529.                                 if( samedev )
  530.                                 {
  531.                                     WaitPkt();
  532.                                     
  533.                                     if( wdp->dp_Res1 != wdp->dp_Arg3 )
  534.                                     {
  535.                                         err = wdp->dp_Res2;
  536.                                         break;
  537.                                     }
  538.                                 }
  539.                                 else
  540.                                 {                                        
  541.                                     index ^= 1;
  542.                                     first  = FALSE;
  543.                                 }
  544.                             }
  545.                         
  546.                             FreeDosObject( DOS_STDPKT, wdp );
  547.                         }
  548.                         
  549.                         FreeDosObject( DOS_STDPKT, rdp );
  550.                     }
  551.                     
  552.                     FreeMem( buffer, allocsize + 15L );
  553.                 }
  554.             }
  555.                                 
  556.             Close( fhin );
  557.             
  558.             if( err )
  559.             {
  560.                 DeleteFile( to );
  561.             }
  562.             else
  563.             {
  564.                 SetComment( to, fib->fib_Comment );
  565.                 SetProtection( to, fib->fib_Protection );
  566.                 SetFileDate( to, &fib->fib_Date );
  567.             }
  568.         }
  569.         else
  570.         {
  571.             err = IoErr();
  572.         }
  573.         
  574.         Close( fhout );
  575.     }
  576.     else
  577.     {
  578.         err = IoErr();
  579.     }
  580.     
  581.     return( err );
  582. }
  583.  
  584. /****************************************************************************/
  585.  
  586. LONG Delete( struct FileInfoBlock *fib, REG( a6, const struct Library *DOSBase ) )
  587. {
  588.     if( fib->fib_Protection & (FIBF_DELETE|FIBF_OTR_DELETE) )
  589.     {
  590.         SetProtection( fib->fib_FileName, fib->fib_Protection & ~(FIBF_DELETE|FIBF_OTR_DELETE) );
  591.     }
  592.                         
  593.     DeleteFile( fib->fib_FileName );
  594.     
  595.     return IoErr();
  596. }
  597.  
  598. /****************************************************************************/
  599.  
  600. LONG CheckLoop( const STRPTR name, BPTR parent, REG( a6, const struct Library *DOSBase ) )
  601. {
  602.     BPTR    cmp, prev = 0L;
  603.     LONG    err = 0L;
  604.     
  605.     if( cmp = Lock( name, SHARED_LOCK ) )
  606.     {    
  607.         do
  608.         {
  609.             if( SameLock( cmp, parent ) )
  610.             {
  611.                 parent = ParentDir( parent );
  612.             }
  613.             else
  614.             {
  615.                 err = ERROR_OBJECT_LINKED;
  616.                 parent = 0L;
  617.             }
  618.                 
  619.             UnLock( prev );
  620.             prev = parent;
  621.         }
  622.         while( parent );        
  623.         
  624.         UnLock( cmp );        
  625.     }
  626.     else
  627.     {
  628.         err = IoErr();
  629.     }
  630.     
  631.     return err;
  632. }
  633.  
  634. /****************************************************************************/
  635.  
  636. void StrnCpy( STRPTR a, STRPTR b, REG( d1, WORD c ) )
  637. {
  638.     do
  639.     {
  640.         if( ! ( *a++ = *b++ ) ) return;
  641.     } 
  642.     while( --c );
  643.     
  644.     *a = '\0';
  645. }
  646.  
  647. /****************************************************************************/
  648.